﻿using Stee.CAP8.MessageBus.Interface.Models;
using Stee.CAP8.MessageBus.Sagas.Core;
using Stee.CAP8.MessageBus.Sagas.Core.Common;
using Stee.CAP8.MessageBus.Sagas.Core.Messages;
using Stee.CAP8.MessageBus.Sagas.Core.Sagas;
using Stee.CAP8.MessageBus.Sagas.Order.Sagas.Data;
using Stee.CAP8.MessageBus.Sagas.Payment.Dtos;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Stee.CAP8.MessageBus.Sagas.Order.Sagas
{
    public class OrderSagaMain : BaseMainSaga<OrderSagaData>
    {

        string userId = Guid.NewGuid().ToString();
        private ConcurrentDictionary<string, OrderInfo> orderlist = new ConcurrentDictionary<string, OrderInfo>();

        public OrderSagaMain(IBus bus, ISagaStorage sagaStorage)
        {
            _bus = bus;
            _sagaStorage = sagaStorage;
        }
        /// <summary>
        /// saga启动
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        public async Task<string> StartSaga(OrderInfo orderInfo)
        {
            //初始化message和sagaData
            var message = new CommandMessage()//call saga
            {
                Action = "Begin",
                CorrelationID = orderInfo.OrderId.ToString(),
                ClientID = userId,
                CreateDT = DateTime.Now,
                JWT = userId.ToString()
            };
            var saga = new OrderSagaData();

            SetCommandMessage(message);
            SetSagaData(saga);
            await CreateOrder(orderInfo);
            return message.CorrelationID;
        }

        /// <summary>
        /// Saga调度逻辑 
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public override async Task HandleReply(CommandMessage message, OrderSagaData saga)
        {
            //从commandmessage中获取应该调用哪个方法

            SetSagaData(saga);
            var actionName = message.Action;
            if (actionName == Data.PaymentAction)
            {
                var payemntInfo = message.Data.ToObject<PaymentInfo>();
                //支付完成
                await HandlePayemented(payemntInfo);
            }
            else if (actionName == Data.StockAdjustAction)
            {
                await HandleAdjustStocked();
            }

        }


        /// <summary>
        /// 创建订单
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task CreateOrder(OrderInfo orderInfo)
        {


            await Task.Run(() =>
            {
                Console.WriteLine("收到商品信息");
                //写数据库
                if (orderInfo != null)
                {
                    this.SaveOrder(orderInfo);
                }
                Data.OrderCreated = true;
                var paymentInfo = new PaymentInfo
                {
                    Amount = orderInfo.Balance,
                    PaymentMethod = "支付宝支付",
                    ThridPartPayNumber = "11212123123"
                };
                //支付操作
                SendCommand(actionName: Data.PaymentAction,
                            topicName: "payment_application",
                            replyChannel: "order_application",
                            instance: paymentInfo);
                var stockInfos = new List<StockInfo> { new StockInfo { Count = 2, ProductSkuNumber = "PE1456789" } };

                //库存调整
                SendCommand(actionName: Data.StockAdjustAction,
                            topicName: "stock_application",
                            replyChannel: "order_application",
                            instance: stockInfos);
            });

        }
        /// <summary>
        /// 子事务支付完成
        /// 记录支付信息
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task HandlePayemented(PaymentInfo paymentInfo)
        {
            Console.WriteLine("支付完成记录");
            Data.OrderCreated = true;

            await Post();
        }
        /// <summary>
        /// 子事务库存调整完成
        /// 记录库存信息
        /// </summary>
        /// <returns></returns>
        public async Task HandleAdjustStocked()
        {
            Console.WriteLine("调整库存成功");
            Data.OrderStockAdjusted = true;
            await Post();
        }
        /// <summary>
        /// 创建订单方法（数据库操作）
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        private OrderInfo SaveOrder(OrderInfo orderInfo)
        {
            return orderlist.AddOrUpdate(orderInfo.OrderId.ToString(), orderInfo, (key, value) =>
            {
                return value;
            });
        }
        /// <summary>
        /// 取消订单方法（数据库操作）
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <returns></returns>
        private bool CancelSaveOrder(OrderInfo orderInfo)
        {
            return orderlist.TryRemove(orderInfo.OrderId.ToString(), out orderInfo);
        }
        private async Task Post()
        {
            if (Data.IsDone)
            {
                Console.WriteLine("事务执行完毕");
            }
            if (Data.IsError)
            {
                await Rollback(null, null, null);
            }
            //发消息到saga发起方
            Console.WriteLine("订单处理完成");
        }

        private async Task Rollback(OrderInfo orderInfo, PaymentInfo paymentInfo, StockInfo stockInfo)
        {
            await Task.Run(() =>
           {
               CancelSaveOrder(orderInfo);
               SendCommand(actionName: Data.PaymentAction,
                         topicName: "payment_application",
                         replyChannel: "order_application",
                         instance: paymentInfo);

               //库存调整
               SendCommand(actionName: Data.StockAdjustAction,
                          topicName: "stock_application",
                          replyChannel: "order_application",
                          instance: stockInfo);
           });
        }




    }
}
